home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------------
- *
- * Apple Developer Technical Support
- *
- * AppleEvent™ Object Model and Object Support Library routines
- *
- * Program:AEObject-Edition Sample
- * File: AEObject.c -C Source
- *
- * by: C.K. Haun <TR>
- *
- * Copyright © 1991,1992 Apple Computer, Inc.
- * All rights reserved.
- *
- *------------------------------------------------------------------------------
- * This file contains most of the routines that deal with AppleEvent Objects, and
- * the routines that use them.
- * Object resolution, and Object accessors play a large part here. Once you under-
- * stand and have written a few accessors, you'll see that this stuff becomes a great
- * deal easier.
- * vers 1.0.1- All AE constants changed to reflect Winter '92 registry
- *----------------------------------------------------------------------------*/
- /* And another Note:
- * I am resolving simple objects in this file and sample. I intend to
- * go on to complex objects in a future sample, please stay tuned */
-
- /* Some words about the objects and handlers */
- /* Windows */
- /* When a window is asked for or used, the token I create is an AEDesc */
- /* of type cWindow, and the data associated with this is */
- /* (suprisingly enough) a window pointer. In this sample I can do anything */
- /* with my data based on a window pointer. */
- /* The rest of the tokens are AEDescs containing structures in the dataHandle, */
- /* please see the AESampStructs.h file for the definition of these structures */
- /* ••• Remember --- A token can be anything you like. It does NOT get passed outside */
- /* your application, it only stays inside it. */
- #define __AEOBJ__
-
- #include "Sampdefines.h"
-
- #pragma segment MyInit
-
- /* InstallObjectHandlers normally would be in the Initialize.c file, but I wanted to put it here, */
- /* along with the rest of the Object Model code so you could see everything in one place */
-
- /* This routine starts the ObjectSupportLibrary, and installs all the callbacks and */
- /* object accessors for this program. */
- OSErr InstallObjectHandlers(void)
- {
- /* Initialize the library. This makes some internal calls to the AppleEvent manager */
- OSErr myErr = AEObjectInit();
- if (!myErr) {
- /* The meat of the initialization. Here I'm installing all the object accessors */
- /* I've written. These are the routines that the OSL will call when I call */
- /* AEResolve on an object in an AppleEvent. These routines do all the */
- /* parsing of the object specifier, segment by segment. Each of them returns a */
- /* token that describes the in-memory structure of the object specified in a way */
- /* my application can understand. No one else will ever see these tokens */
- /* they are ONLY for use inside my program. This means that they can be anything that */
- /* makes sense to me and my appliction. */
- /* The actual token structures I use are defined in the AESampStructs.h file. */
- /* This accessor returns a window token from a null descriptor. This */
- /* accessor will be called a LOT, since specifing anything in my application */
- /* will usually reference an owning window. */
-
- myErr = AEInstallObjectAccessor(cWindow, typeNull, NewOSLAccessorProc(WindFromNull), 0, false);
-
- /* This accessor gets ANY property from a window token */
- /* Since a window token describes all the important junk about the window */
- /* I only need one property from window accessor */
-
- myErr = AEInstallObjectAccessor(typeProperty, cWindow, NewOSLAccessorProc(PropertyFromWindow), 0, false);
-
- /* This installs my Text from Window accessor. If there is a text object in this window */
- /* this routine will return a token for it */
-
- myErr = AEInstallObjectAccessor(cText, cWindow, NewOSLAccessorProc(TextFromWindow), 0, false);
-
- /* Now be able to pass back properties of my Text objects */
-
- myErr = AEInstallObjectAccessor(typeProperty, cText, NewOSLAccessorProc(PropertyFromText), 0, false);
-
- /* This installs my Word from Text accessor. */
-
- myErr = AEInstallObjectAccessor(cWord, cText, NewOSLAccessorProc(WordFromText), 0, false);
-
- myErr = AEInstallObjectAccessor(cDrawingArea, cWindow, NewOSLAccessorProc(DrawFromWindow), 0, false);
-
- /* This guy graps a graphic shape from my window, no matter what it actually is */
-
- myErr = AEInstallObjectAccessor(cGraphicShape, cDrawingArea, NewOSLAccessorProc(ShapeFromDraw), 0, false);
- myErr = AEInstallObjectAccessor(cGraphicShape, cWindow, NewOSLAccessorProc(ShapeFromDraw), 0, false);
- /* these grab specific shapes from the drawing area */
- /* The canny observer will notice that these all call the ShapeFromDraw routine */
- /* Since my shapes are all defined in the same type of structure, this makes */
- /* a lot of sense for me */
-
- myErr = AEInstallObjectAccessor(cGraphicLine, cDrawingArea, NewOSLAccessorProc(ShapeFromDraw), 0, false);
- myErr = AEInstallObjectAccessor(cOval, cDrawingArea, NewOSLAccessorProc(ShapeFromDraw), 0, false);
- myErr = AEInstallObjectAccessor(cRectangle, cDrawingArea, NewOSLAccessorProc(ShapeFromDraw), 0, false);
- myErr = AEInstallObjectAccessor(cGraphicLine, cWindow, NewOSLAccessorProc(ShapeFromDraw), 0, false);
- myErr = AEInstallObjectAccessor(cOval, cWindow, NewOSLAccessorProc(ShapeFromDraw), 0, false);
- myErr = AEInstallObjectAccessor(cRectangle, cWindow, NewOSLAccessorProc(ShapeFromDraw), 0, false);
-
- /* and the same type o' thing for shape properties */
- myErr = AEInstallObjectAccessor(typeProperty, cGraphicLine, NewOSLAccessorProc(PropertyFromShape), 0, false);
- myErr = AEInstallObjectAccessor(typeProperty, cOval, NewOSLAccessorProc(PropertyFromShape), 0, false);
- myErr = AEInstallObjectAccessor(typeProperty, cRectangle, NewOSLAccessorProc(PropertyFromShape), 0, false);
-
-
-
- /* And the list will go on and on. Once you've written a few accessors, you realize */
- /* how handy they are, and you start installing them for everything that can */
- /* possibly be gotten from anything else. The only limit will be the */
- /* amount of code space you want to dedicate to accessors. */
- /* Remember, the more accessors you put in, the more ways users will have to */
- /* get at your data, and the less they will have to learn or remember. */
- /* Our goal, as always, is to make it as easy for the user as possible. */
- /* I will also use the same routine to go from a null */
-
- /* Here I am installing all the call back routines that the OSL needs. */
- /* These are not all implemented as doing something, but they will eventually */
- /* These tokens will be called by the OSL as it does it's parsing */
- /* thrugh a passed object specifier. */
- /* You may not need all of these, any you don't need just pass */
- /* a nil */
-
- myErr = AESetObjectCallbacks(NULL,
- NewOSLCountProc(MyCountProc),
- NewOSLDisposeTokenProc(MyDisposeTokenProc),
- NULL, NULL, NULL, NULL);
-
- }
- return(myErr);
- }
-
-
- #pragma segment AEOSL
- /* My GetData event handler. This routine resolves the object passed (calling AEResolve) */
- /* and then returns the appropriate data to the sender of the event */
- pascal OSErr AEGetDataHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
- {
- #pragma unused (refIn)
-
- OSErr myErr = noErr;
- AEDesc tokenBack;
- AEDesc theObject;
- AEDesc returnDesc;
- /* variables for the various tokens I'll be getting back */
- CWordObjHandle wordToken;
- CTextObjHandle textToken;
- PropertyTHdl propertyToken;
- Handle myDataHandle, tempHandle;
- Size dataSize;
- /* window is just a window ptr */
- gCurrentReply = reply;
- mVerboseOutput("\p\nEntering GetData handler")
- myErr = AEGetParamDesc(messagein, keyDirectObject, typeObjectSpecifier, &theObject);
- mAEErrorDisplay("\p getting object spec", myErr)
- if (!myErr) {
- returnDesc.descriptorType = typeNull; /* set this up for a later check */
- myErr = AEResolve(&theObject, kAEIDoMinimum, &tokenBack);
- mAEErrorDisplay("\p AEResolve", myErr)
-
- if (!myErr) {
- /* Hey, marvy, we got an object token back. That means that we have */
- /* enough information to derive the data. */
- /* Again, and forever, we don't care how you actually access data and create tokens */
- /* inside your application, you know how to do that much bettern than we ever will. */
- /* As long as it makes sense, and is efficient, for you, it's fine with us. */
- /* I am going to have to do some switching and stuff here to put the data I got into the reply */
-
- /* By the Way: You could make all your tokens with the same field for the */
- /* data and descriptor type. If you did that, you wouldn't need the case */
- /* here for a GetData event, you would just pass back what you got. */
- /* I thought about it for this sample, but it seems more descriptive to */
- /* go through the specific objects. I may change my mind.... */
-
- /* Anyway, I switch off the type of token I got back... */
- switch (tokenBack.descriptorType) {
- case cWindow:
- /* for this, I'm going to pass back the Window ID I use in this program. */
- /* Why not the window pointer? Because we don't have shared memory in the current */
- /* Mac OS, so I don't want people mucking around in my windows directly. */
- /* And really, if you're getting a request for a bare window, all the other side */
- /* is probably trying to see is if a window exisits. I hope. */
- /* they can pass back this as a selector for NewElement, or something */
- /* You won't see this for a GetData much, in fact you can't from this */
- /* sample get it. I mean it ain't in the GetData menu */
-
- break;
- case cText:
- /* Pass back the chunk o' text. Since I'm using TextEdit, I know that I'll */
- /* never be over 32k here. Keep in mind that the AppleEvent manager can only */
- /* handle data up to 64k, so if you are passing back more text (or whatever) */
- /* than that you'll have to do it in a series of returns, or pass back an */
- /* alias to a file, or some such. */
- textToken = (CTextObjHandle)tokenBack.dataHandle;
- myDataHandle = (Handle)TEGetText((*textToken)->theText);
- HLock(myDataHandle);
- dataSize = GetHandleSize(myDataHandle);
- /* again, this check is not really necessary, but I want to put it here */
- /* as a warning, and maybe someday I'll stop using TextEdit. */
- if (dataSize > k64k) {
- /* if this were true, you would have to do something. */
- dataSize = k64k;
- }
- myErr = AECreateDesc(typeChar, (Ptr)*myDataHandle, dataSize, &returnDesc);
- HUnlock(myDataHandle);
- /* and kill the remaining token */
- myErr = MyDisposeTokenProc(&tokenBack);
- /* the descriptor will be added to the reply later in this function */
- break;
- case cWord:
- /* same basic thing for a word as for a text */
- wordToken = (CWordObjHandle)tokenBack.dataHandle;
- myDataHandle = NewHandle((*wordToken)->endPos - (*wordToken)->startPos);
- HLock(myDataHandle);
- dataSize = GetHandleSize(myDataHandle);
- /* move the text from the te chars handle to my data handle */
- tempHandle = (Handle)TEGetText((*wordToken)->theText);
- HLock(tempHandle);
- BlockMove((Ptr)(*tempHandle + (*wordToken)->startPos), (Ptr)*myDataHandle, dataSize);
- HUnlock(tempHandle);
- /* again, this check is not really necessary, but I want to put it here */
- /* as a warning. */
- if (dataSize > k64k) {
- /* if this were true, you would have to do something. */
- dataSize = k64k;
- }
- myErr = AECreateDesc(typeChar, (Ptr)*myDataHandle, dataSize, &returnDesc);
- HUnlock(myDataHandle);
- /* return value will be added to reply later in this function */
- /* and kill the remaining token */
- myErr = MyDisposeTokenProc(&tokenBack);
-
- break;
- case typeProperty:
- /* just return the property as the type included in the token */
- /* The SetData handler (as you will see) needs to do a lot more */
- propertyToken = (PropertyTHdl)tokenBack.dataHandle;
- HLock((Handle)propertyToken);
- myDataHandle = (*propertyToken)->theData;
- dataSize = GetHandleSize(myDataHandle);
- /* again, this check is not really necessary, but I want to put it here */
- /* as a warning. */
- if (dataSize > k64k) {
- /* if this were true, you would have to do something. */
- dataSize = k64k;
- }
- HLock(myDataHandle);
- myErr = AECreateDesc((*propertyToken)->theDataType, (Ptr)*myDataHandle, dataSize, &returnDesc);
- myErr = MyDisposeTokenProc(&tokenBack);
- break;
- /* and others as I add them */
- case cGraphicShape:
- case cGraphicLine:
- MakeGraphicLine((CShapeObjHandle)tokenBack.dataHandle, &returnDesc);
- myErr = MyDisposeTokenProc(&tokenBack);
- break;
- case cRectangle:
- case cOval:
- /* both of these have a default descriptor type of typeRectange, so I'll go make that */
- MakeTypeRect((CShapeObjHandle)tokenBack.dataHandle, &returnDesc);
- myErr = MyDisposeTokenProc(&tokenBack);
- break;
-
- }
-
- /* Here I either have a good descriptor for a return value, or I have */
- /* 'null' in the type field if something went wrong. */
- if (returnDesc.descriptorType == typeNull) {
- /* something bad happend, there will be no reply. */
- /* the error is already in myErr */
- } else {
- AEDesc newDesc;
- AEDesc wantType;
- OSErr tempErr;
- /* we have a good descriptor. THere's one more thing to do, and it's */
- /* technically optional, but you should support it if you can. That's */
- /* seeing if the sender included a type that the wanted the data back as. */
- /* if they did, I will try and coerce my return descriptor to that type */
- /* First, is there a wantType? */
- /* I equate this to tempErr instead of myErr because it is not fatal if */
- /* this get fails, I don't want to pass this error back to the sender */
-
-
- tempErr = AEGetParamDesc(messagein, keyAERequestedType, typeType, &wantType);
- if (!tempErr) {
- /* there was a wantType. Try and coerce my data to that type */
- /* If the coercion fails, I will just return my type of data. The */
- /* sender of this event may be able to do the coercion on their */
- /* end, perhaps they have more coercion handlers on their machine */
- /* • NOTE: DON'T assume that you can't coerce the descriptor! */
- /* i.e. don't evaluate the wantType yourself and say */
- /* "my application doesn't know how to do that" and fail. */
- /* True, your app may not know. But someone else on the */
- /* machine MIGHT know, and they may have installed a system */
- /* level coercion routine that will make this work even if */
- /* your application knew nothing about it. So try the coercion */
- tempErr = AECoerceDesc(&returnDesc, (DescType)**(wantType.dataHandle), &newDesc);
- if (!tempErr) {
- AEDesc tempDesc;
- /* it coerced. So, because of the way I'm doing this, swap */
- /* things around (kinda) */
- tempDesc = returnDesc;
- returnDesc = newDesc;
- AEDisposeDesc(&tempDesc);
- }
- }
-
- myErr = AEPutParamDesc(reply, keyDirectObject, &returnDesc);
- myErr = AEDisposeDesc(&returnDesc);
-
- }
- } /* aeresolve error */
- } /* get object */
- gCurrentReply = nil;
- return(myErr);
-
- }
-
- pascal OSErr AESetDataHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
- {
- #pragma unused (refIn)
- OSErr myErr = noErr;
- PropertyTHdl propertyBack;
- CTextObjHandle cTextBack;
- CWordObjHandle cWordBack;
- AEDesc tokenBack;
- AEDesc theObject;
- AEDesc theData;
- gCurrentReply = reply;
- mVerboseOutput("\p\nEntering SetData handler")
- myErr = AEGetParamDesc(messagein, keyDirectObject, typeObjectSpecifier, &theObject);
-
- mAEErrorDisplay("\p getting object spec", myErr)
- /* get the data to set now also. If we don't have any data, we can't */
- /* do this event. */
- /* I'm asking for the data as typeWildCard, so no coercions will take place. */
- /* I may coerce the data later, but now I want it as sent. */
- myErr = AEGetParamDesc(messagein, keyAEData, typeWildCard, &theData);
- mAEErrorDisplay("\p getting the data", myErr)
- myErr = AEResolve(&theObject, kAEIDoMinimum, &tokenBack);
- mAEErrorDisplay("\p AEResolve", myErr)
- if (!myErr) {
- /* we have a token telling us what the object to set is. */
- /* from that, we can do our setting */
- /* How you actually implement this is again very much up to */
- /* you. This is only a simple sample, do what seems best in your application */
- switch (tokenBack.descriptorType) {
- case cWindow:
- /* this shouldn't ever come back, since you can't set a */
- /* window per sé. Look at the property switch for that stuff */
- break;
- case cText:
- /* setting the text of this text token */
- /* our text token contains a TEHandle, so here's what we'll do.... */
- cTextBack = (CTextObjHandle)tokenBack.dataHandle;
- /* select all the text */
- TESetSelect(0, 32000, (*cTextBack)->theText);
- /* kill the old text */
- TEDelete((*cTextBack)->theText);
- HLock(theData.dataHandle);
- /* and set the new text */
- TESetText((Ptr)*(theData.dataHandle), GetHandleSize((theData.dataHandle)), (*cTextBack)->theText);
- HUnlock(theData.dataHandle);
- /* fìn */
- MyDisposeTokenProc(&tokenBack);
- break;
- case cWord:
- /* changing this one word to something else */
- /* basically the same as setting text, our range is just delimited */
- /* setting the text of this text token */
- /* our text token contains a TEHandle, so here's what we'll do.... */
- cWordBack = (CWordObjHandle)tokenBack.dataHandle;
- /* select all the text */
- TESetSelect((*cWordBack)->startPos, (*cWordBack)->endPos, (*cWordBack)->theText);
- TEDelete((*cWordBack)->theText);
- HLock(theData.dataHandle);
- TEInsert((Ptr)*(theData.dataHandle), GetHandleSize((theData.dataHandle)), (*cWordBack)->theText);
- /* fìn */
- MyDisposeTokenProc(&tokenBack);
- break;
- case typeProperty:
- propertyBack = (PropertyTHdl)tokenBack.dataHandle;
- /* since there are so many properties to set, I'll switch off */
- /* the owner and set to that type */
- switch ((*propertyBack)->owningTokenType) {
- case cWindow:
- myErr = SetWindowProperty(propertyBack, &theData); /* in Windows.c */
- MyDisposeTokenProc(&tokenBack);
- break;
- case cText:
- case cWord:
- /* I'm not setting text or word properties in this sample, since I'm */
- /* using plain old TextEdit (not even style) */
- myErr = errAENotModifiable;
- AddToReply("\p Text property setting not implemented",0);
- break;
- case cGraphicLine:
- case cRectangle:
- case cOval:
- myErr = SetShapeProperty(propertyBack, &theData); /* in Windows.c */
- MyDisposeTokenProc(&tokenBack);
- break;
-
- case typeProperty:
- /* uhhh, if you ever have to set the property of a proprty, call me */
- /* and we'll find help */
- break;
-
- }
- break;
- }
- }
- gCurrentReply = nil;
- return(myErr);
- }
-
- /* TextFromWindow returns a token identifying a text object attached to a window. */
- /* If there is no text in this window, it returns an error */
- pascal OSErr TextFromWindow(DescType desiredClass, const AEDesc *container, DescType containerClass, DescType form,
- const AEDesc *selectionData, AEDesc *value, long LongInt)
- {
- #pragma unused (desiredClass,form,LongInt)
- OSErr myErr = noErr;
- WindowPtr theWindow;
- windowCHandle tempWC;
- short textNumber;
- CTextObjHandle newText;
-
- mVerboseOutput("\p\nGetting a Text from a Window")
- if (containerClass != cWindow) {
- myErr = errAENoSuchObject; /* no such luck speedy */
- AddToReply("\pYou did not ask for a text from a window, it's container", 0);
- } else {
- /* the container contains a window token in it's hot little datahandle */
- theWindow = *((WindowPtr *)(*(container->dataHandle)));
-
- tempWC = (windowCHandle)GetWRefCon(theWindow);
- /* Does this window contain a text edit record???? */
- if ((*tempWC)->boxHandle) {
- /* which number Text did they ask for? Our sample only allows one */
- /* Text per window, so if it isn't one, bail */
- ShortFromDesc(&textNumber, selectionData);
- if (textNumber == 1) {
- /* create an cText object and pass it back */
- newText = (CTextObjHandle)NewHandle(sizeof(CTextObject));
- HLock((Handle)newText);
- /* fill it in */
- (*newText)->theOwningWindow = theWindow;
- (*newText)->theText = (*tempWC)->boxHandle;
- myErr = AECreateDesc(cText, (Ptr)*newText, sizeof(CTextObject), value);
- DisposeHandle((Handle)newText); /* no longer needed */
- } else {
- myErr = errAENoSuchObject;
- AddToReply("\pNo Text Box with that index", 0);
- }
- } else {
- /* no text in this window */
- myErr = errAENoSuchObject;
- AddToReply("\pNo Text Box in the window you specified", 0);
- }
- }
- return(myErr);
- }
-
- /* Grab a word from the text */
- /* This is a 3rd level call from AEResolve. Before we got to here, AEResolve has */
- /* already called our WindFromNull and TextFromWindow accessors, the container */
- /* passed in is our text container token (probably) */
- pascal OSErr WordFromText(DescType desiredClass, const AEDesc *container, DescType containerClass, DescType form,
- const AEDesc *selectionData, AEDesc *value, long LongInt)
- {
- #pragma unused (desiredClass,containerClass,form,LongInt)
- OSErr myErr = noErr;
- long wordCount;
- long wordStart;
- long wordEnd;
- short countToGet;
- SignedByte textHState;
- CWordObjHandle wordToken;
- Handle theText;
- /* Since we'e getting word from text, we know the container is our Text token */
- CTextObjHandle ourTextObject = (CTextObjHandle)(container->dataHandle);
- /* grab the text for later */
- theText = (Handle)TEGetText((*ourTextObject)->theText);
- textHState = HGetState(theText);
- HLock(theText);
- if (GetHandleSize(theText)) {
- mVerboseOutput("\p\nGetting a word from a Text")
- ShortFromDesc(&countToGet, selectionData);
-
- /* call my word counter with a stopAt of the selection data */
- CountWords(container, &wordCount, countToGet, &wordStart);
- /* CountWords returns negative if there weren't any, or if we went too far */
- if (wordCount > 0) {
- /* now count to the next word, so we know the range */
- /* I know, I know, this is horribly inefficient, but it's an example, OK? */
- CountWords(container, &wordCount, countToGet + 1, &wordEnd);
- if (wordCount < 0) {
- /* ooops, no more words. Just go to text len then */
- wordEnd = GetHandleSize(theText);
- }
- /* return a word token */
- wordToken = (CWordObjHandle)NewHandleClear(sizeof(CWordObject));
- /* fill in the token */
- (*wordToken)->theOwningWindow = (*ourTextObject)->theOwningWindow;
- (*wordToken)->theText = (*ourTextObject)->theText;
- (*wordToken)->startPos = wordStart;
- (*wordToken)->endPos = wordEnd;
- /* create the token */
- myErr = AECreateDesc(cWord, (Ptr)*wordToken, sizeof(CWordObject), value);
- } else {
- /* error, no words */
- myErr = errAENoSuchObject;
- AddToReply("\pCould not find this number word in this text", 0);
- }
- } else {
- myErr = errAENoSuchObject;
- AddToReply("\pNo words in this Text", 0);
- }
- HSetState(theText, textHState);
- return(myErr);
- }
-
- pascal OSErr DrawFromWindow(DescType desiredClass, const AEDesc *container, DescType containerClass, DescType form,
- const AEDesc *selectionData, AEDesc *value, long LongInt)
- {
- #pragma unused (desiredClass,containerClass,form,selectionData,LongInt)
- OSErr myErr = noErr;
- mVerboseOutput("\p\nGetting a Drawing Area from a window")
- /* the drawing area token is the same as a window token (i.e. a window pointer) since it gives */
- /* us everything we need to know */
- /* so basically we duplicate the descriptor passed in to us, then change the descType */
- myErr = AEDuplicateDesc(container, value);
- value->descriptorType = cDrawingArea;
- return(myErr);
- }
-
- /* ShapeFromDraw pulls _any_ kind of shape from my drawing area. It's called for */
- /* a generic cGraphicShape, a cGraphicLine,cRectangle, and cOval. This is where */
- /* your code gets optimized and shrunken, so it is not the nightmare you */
- /* at first thought. Really */
- /* Note that this also gets called for shapes from cWindow (if someone asks that way) */
- /* so golly, it's just so useful */
- pascal OSErr ShapeFromDraw(DescType desiredClass, const AEDesc *container, DescType containerClass, DescType form,
- const AEDesc *selectionData, AEDesc *value, long LongInt)
- {
- #pragma unused (LongInt)
- OSErr myErr = noErr;
- windowCHandle tempWC;
- long selNumber;
- long tempCounter;
- CShapeObjHandle theToken = (CShapeObjHandle)NewHandleClear(sizeof(CShapeObject));
- ShapesHandle theShapes;
- short numShapes;
- mVerboseOutput("\p\nGetting a Shape from a window, specifically a ")
- AddToAEWindow((Ptr)&desiredClass, kFour);
- /* the container may be either a cWindow or a cDrawingArea. In our infinite wisdom, */
- /* we have made these tokens the same, so we can use the same routine for both. */
- if (containerClass == cWindow || containerClass == cDrawingArea) {
- /* get the right window struct and the shapes attached to it */
- tempWC = (windowCHandle)GetWRefCon(*((WindowPtr *)(*(container->dataHandle))));
- theShapes = (*tempWC)->theShapes;
- numShapes = (*tempWC)->numShapes;
- /* do some default filling of the shape token, since there's some things */
- /* we already know */
- (*theToken)->theOwningWindow = *((WindowPtr *)(*(container->dataHandle)));
- (*theToken)->type = typeNull; /* flag for later folks */
- if (numShapes) {
- /* case off the type of shape we're asking for for the specific one */
- switch (desiredClass) {
- case cGraphicShape:
- /* just any old thing */
- /* case off the form wanted. Since I am only sending myself graphics */
- /* by index, that's the case I'll do first */
- case cGraphicLine:
- case cRectangle:
- case cOval:
- /* and all these shapes are basically the same, so I'll use the same routine */
- /* in fact, I'm going to go back to my window routine and make the type filed in my Shapes */
- /* handle a desc type, hold on a minute.... OK, I'm back, this will make it even easier */
- switch (form) {
- case formAbsolutePosition:
- if (selectionData->descriptorType == typeLongInteger) {
-
- selNumber = *((long *)*(selectionData->dataHandle));
- } else {
- /* see if you can coerce it to a long */
- }
- /* find the selNumber-th line in this drawing area */
- if (selNumber == 0)
- selNumber = 1; /* no 0th */
- tempCounter = 0;
- while (theShapes) {
- /* 'if' here depending on generic shape or specific type */
- if (desiredClass == cGraphicShape) {
- tempCounter++; /* doesn't matter what kind, we care about it */
- } else {
- if ((*theShapes)->aeType == desiredClass)
- tempCounter++;
- }
- if (tempCounter == selNumber) {
- break;
- } else {
- theShapes = (*theShapes)->nextShape;
- }
- }
- /* if theShapes is not nil, then we found a shape that suites */
-
- if (theShapes) {
- /* fill in my token */
- (*theToken)->theShape = theShapes;
- (*theToken)->shapeNumber = tempCounter; /* why do I want this? I dunno */
- (*theToken)->type = desiredClass;
- } else {
- myErr = errAENoSuchObject;
- }
- break;
- case formRelativePosition: /* next, previous */
- break;
- case formTest: /* A logical or a comparison */
- break;
- case formRange: /* Two arbitrary objects and everything in between */
- break;
- case formPropertyID: /* Key data is a 4-char property name */
- break;
- case formName: /* Key data may be of type 'TEXT' */
-
- break;
- default:
- myErr = errAENoSuchObject;
- break;
- }
- break;
- }
- } else {
- /* no shapes with this window */
- myErr = errAENoSuchObject;
- }
- } else {
- myErr = errAENoSuchObject;
- }
- if (myErr == noErr && (*theToken)->type != typeNull) {
- HLock((Handle)theToken);
- myErr = AECreateDesc((*theToken)->type, (Ptr)*theToken, sizeof(CShapeObject), value);
- DisposeHandle((Handle)theToken);
- }
- return(myErr);
- }
-
- /* In this example, this will be the first accessor called by any call to AEResolve. */
- /* Since we have no other objects sprouting from null but windows, anyone who */
- /* wants to know about our documents has to have a cWindow object spec hanging off the */
- /* topmost null. */
- pascal OSErr WindFromNull(DescType desiredClass, const AEDesc *container, DescType containerClass, DescType form,
- const AEDesc *selectionData, AEDesc *value, long LongInt)
- {
- #pragma unused (desiredClass,container,LongInt)
- WindowPtr returnedWindow = nil;
- WindowPtr tempWindow = nil;
- short index = 0;
- short counter = 0;
- OSErr myErr = noErr;
- Str63 tempMatch;
- Str63 windowName;
-
- mVerboseOutput("\p\nGetting a Window from Nul")
- /* first check to see if we can deal with this, are they asking for a window from Nul? */
- /* If they're not then we can't handle it */
- if (containerClass != typeNull)
- return(errAENoSuchObject); /* not something we recognize */
- /* case off form to see how we'll get the window thing */
- /* all of these may not be supported, but as time goes by they will be */
-
- switch (form) {
- case formAbsolutePosition: /* e.g., 1st, -2nd ( 2nd from end) */
- /* ignore the AEStatusWindow in searching this list */
- tempWindow = FrontWindow();
- /* a little utilty routine, see which number window they want */
- ShortFromDesc(&index, (AppleEvent *)selectionData);
- if (index == 0)
- index = 1;
- if (index == 1 && (((WindowPeek)FrontWindow())->windowKind != kAEStatusWindow)) {
- /* just grab the front window and return */
- returnedWindow = FrontWindow();
- } else {
- /* walk the list */
- tempWindow = (WindowPtr)LMGetWindowList();
- while (tempWindow) {
- windowCHandle tempWC = (windowCHandle)GetWRefCon(tempWindow);
- if (index == (*tempWC)->windowIndex) {
- returnedWindow = tempWindow;
- break;
- }
- tempWindow = (WindowPtr)((WindowPeek)tempWindow)->nextWindow;
- }
- }
- if (returnedWindow) {
-
- myErr = AECreateDesc(cWindow, (Ptr)&returnedWindow, sizeof(returnedWindow), value);
- mAEErrorDisplay("\p creating object token", myErr);
- } else {
- /* error, couldn't find the thing */
- myErr = errAENoSuchObject;
- AddToReply("\pNo window of that index number", 0);
- }
- break;
- case formRelativePosition: /* next, previous */
- break;
- case formTest: /* A logical or a comparison */
- break;
- case formRange: /* Two arbitrary objects and everything in between */
- break;
- case formPropertyID: /* Key data is a 4-char property name */
-
- break;
- case formName: /* Key data may be of type 'TEXT' */
- /* gettting one of these here things by name */
- /* so the AEDesc has a text thing in it. Not a PString, just a charater thing, */
- /* so I'll make it a PString */
- PStringFromTextDesc(&tempMatch, selectionData);
- /* and as usual, walk the window list */
- tempWindow = FrontWindow();
- while (tempWindow) {
- GetWTitle(tempWindow, windowName);
- if (EqualString(windowName, tempMatch, false, false))
- break;
- tempWindow = (WindowPtr)((WindowPeek)tempWindow)->nextWindow;
- }
- if (tempWindow) {
- /* we have a match */
- myErr = AECreateDesc(cWindow, (Ptr)&tempWindow, sizeof(tempWindow), value);
- mAEErrorDisplay("\p creating object token", myErr);
- } else {
- /* no match, return an error */
- myErr = errAENoSuchObject;
- AddToReply("\pNo window with that name", 0);
- }
- break;
-
- }
- return(myErr);
- }
-
- /* PropertyFromWindow gets all the properties of my window object. */
- pascal OSErr PropertyFromWindow(DescType desiredClass, const AEDesc *container, DescType containerClass, DescType form,
- const AEDesc *selectionData, AEDesc *value, long LongInt)
- {
- #pragma unused (desiredClass,containerClass,form,LongInt)
-
- OSErr myErr = noErr;
- Str63 windowName;
- WindowPtr tempPort;
- PropertyTHdl propertyTokenH = (PropertyTHdl)NewHandleClear(sizeof(PropertyToken));
- /* pull a property from the window */
- DescType propertyType = *(DescType *)(*(selectionData->dataHandle));
- ProcessSerialNumber tempPSN;
- Boolean tempBool;
- Handle theData;
- WindowPtr owningWindow;
- windowCHandle owningControl;
- mVerboseOutput("\p\n Getting a window property ")
- AddToAEWindow((Ptr)&propertyType, kFour);
- /* I can fill in some of the token information right now, since I have the window */
- owningWindow = *((WindowPtr *)(*(container->dataHandle)));
- owningControl = (windowCHandle)GetWRefCon(owningWindow);
- (*propertyTokenH)->owningTokenType = cWindow; /* what this is a property of */
- (*propertyTokenH)->token.window = owningWindow;
- (*propertyTokenH)->inWindow = owningWindow; /* for consistency, though it's redundant */
- switch (propertyType) {
- /* can't get all of them yet, as this sample grows the amount of properties will also */
- /* grow */
-
- /* What's the name of this window? */
- case pName:
- (*propertyTokenH)->theProperty = pName;
- (*propertyTokenH)->theDataType = typeChar;
- GetWTitle(owningWindow, windowName);
- theData = NewHandle(windowName[0]);
- HLock(theData);
- BlockMove((Ptr)&windowName[1], (Ptr)*theData, windowName[0]);
- HUnlock(theData);
- (*propertyTokenH)->theData = theData;
- break;
- /* Boundry rectangle, in global coordinates */
- case pBounds:
- (*propertyTokenH)->theProperty = pBounds;
- (*propertyTokenH)->theDataType = typeQDRectangle;
- theData = NewHandle(sizeof(Rect));
- HLock(theData);
- BlockMove((Ptr)&owningWindow->portRect, (Ptr)*theData, sizeof(Rect));
- /* now we have to globalize the coordiantes */
- GetPort(&tempPort);
- SetPort(owningWindow);
- SetPort(tempPort);
- /* Now, can we force the MPW C compiler to beleive us that what we're passing is */
- /* a Point pointer???? */
- LocalToGlobal((Point *)*theData);
- LocalToGlobal((Point *)(*theData + sizeof(Point)));
- /* yes we can, amazing */
-
- HUnlock(theData);
- (*propertyTokenH)->theData = theData;
-
- break;
- /* Do we have a title bar? */
- case pHasTitleBar:
- (*propertyTokenH)->theProperty = pHasTitleBar;
- (*propertyTokenH)->theDataType = typeBoolean;
- theData = NewHandle(sizeof(short));
- **theData = kMyTrue; /* they all do */
- (*propertyTokenH)->theData = theData;
- break;
- /* are we a modal window? */
- case pIsModal:
- (*propertyTokenH)->theProperty = pIsModal;
- (*propertyTokenH)->theDataType = typeBoolean;
- theData = NewHandle(sizeof(short));
- **theData = ((WindowPeek)owningWindow)->windowKind & dialogKind;
- (*propertyTokenH)->theData = theData;
- break;
- /* is this window 'dirty'? */
- case pIsModified:
- (*propertyTokenH)->theProperty = pIsModified;
- (*propertyTokenH)->theDataType = typeBoolean;
- theData = NewHandle(sizeof(short));
- **theData = (*owningControl)->windowDirty;
- (*propertyTokenH)->theData = theData;
- break;
- /* can the size be changed? */
- case pIsResizable:
- (*propertyTokenH)->theProperty = pIsResizable;
- (*propertyTokenH)->theDataType = typeBoolean;
- theData = NewHandle(sizeof(short));
- **theData = kMyTrue;
- (*propertyTokenH)->theData = theData;
- break;
- /* stationary? */
- case pIsStationeryPad:
- (*propertyTokenH)->theProperty = pIsResizable;
- (*propertyTokenH)->theDataType = typeBoolean;
- theData = NewHandle(sizeof(short));
- **theData = false;
- (*propertyTokenH)->theData = theData;
- break;
- /* Are we in the users face right now? */
- case pIsFrontProcess:
- (*propertyTokenH)->theProperty = pIsResizable;
- (*propertyTokenH)->theDataType = typeBoolean;
- theData = NewHandle(sizeof(short));
- GetFrontProcess(&tempPSN);
- SameProcess(&tempPSN, &gOurSN, &tempBool);
- **theData = tempBool;
- (*propertyTokenH)->theData = theData;
- break;
- /* are we in the Zoomed state? */
- case pIsZoomed:
- break;
- /* are we visible to the user now? */
- case pVisible:
- (*propertyTokenH)->theProperty = pVisible;
- (*propertyTokenH)->theDataType = typeBoolean;
- theData = NewHandle(sizeof(short));
- **theData = kMyTrue; /* I'm only returning visible windows */
- (*propertyTokenH)->theData = theData;
- break;
- /* What's our class? */
- case pClass:
- (*propertyTokenH)->theProperty = pClass;
- (*propertyTokenH)->theDataType = typeType;
-
- theData = NewHandle(sizeof(DescType));
- HLock(theData);
- *((DescType *)*theData)=cWindow;
- HUnlock(theData);
- (*propertyTokenH)->theData = theData;
-
- break;
-
- }
-
- /* and return the token */
- if (!myErr) {
- HLock((Handle)propertyTokenH);
- myErr = AECreateDesc(typeProperty, (Ptr)*propertyTokenH, sizeof(PropertyToken), value);
- /* dispose of the token handle, but NOT the data handle I added, since the AEM */
- /* had no idea that I put a handle inside the data, so it didn't copy that */
- /* Later, when the token itself is disposed that handle will be */
- /* freed up. */
- DisposeHandle((Handle)propertyTokenH);
- mAEErrorDisplay("\p creating property token", myErr);
-
- }
- return(myErr);
- }
- /* This allows someone to get properties from my text */
- pascal OSErr PropertyFromText(DescType desiredClass, const AEDesc *container, DescType containerClass, DescType form,
- const AEDesc *selectionData, AEDesc *value, long LongInt)
- {
- #pragma unused (desiredClass,containerClass,form,value,LongInt)
-
- OSErr myErr = noErr;
- PropertyTHdl propertyTokenH = (PropertyTHdl)NewHandleClear(sizeof(PropertyToken));
- CTextObjHandle myTextHandle; /* I include a text object token in my text property token */
- /* kinda circular, but hey... */
- /* pull a property from a text */
-
- DescType propertyType = *(DescType *)(*(selectionData->dataHandle));
- Handle theData;
- RGBColor myBlack = {
- 0, 0, 0
- }; /* for the Color question */
- Str255 tempString;
- windowCHandle owningControl;
- mVerboseOutput("\p\n Getting a text property ")
- AddToAEWindow((Ptr)&propertyType, kFour);
- /* I can fill in some of the token information right now, since I have the window */
- myTextHandle = (CTextObjHandle)container->dataHandle;
- owningControl = (windowCHandle)GetWRefCon((*myTextHandle)->theOwningWindow);
- (*propertyTokenH)->owningTokenType = cText; /* what this is a property of */
- (*propertyTokenH)->token.textHandle = (*myTextHandle)->theText;
- (*propertyTokenH)->theProperty = propertyType;
- (*propertyTokenH)->inWindow = (*myTextHandle)->theOwningWindow;
- switch (propertyType) {WritingCodePtr theCode;
-
- case pAnyCharTextStyles:
- (*propertyTokenH)->theDataType = typeBoolean;
- theData = NewHandle(sizeof(short));
- **theData = false; /* we have no style */
- (*propertyTokenH)->theData = theData;
- break;
- case pClass:
- (*propertyTokenH)->theDataType = typeType;
- theData = NewHandle(sizeof(DescType));
- **theData = cText; /* they all do */
- (*propertyTokenH)->theData = theData;
- break;
- case pColor:
- (*propertyTokenH)->theDataType = typeRGBColor;
- /* always black in this example */
- theData = NewHandle(sizeof(RGBColor));
- HLock(theData);
- BlockMove((Ptr)&myBlack, (Ptr)*theData, sizeof(RGBColor));
- HUnlock(theData);
- (*propertyTokenH)->theData = theData;
- break;
- case pFont:
- /* get the ID, translate to a name, and return as text */
- /* our token contains a TERecord, which contains the font ID */
- GetFontName((*(*propertyTokenH)->token.textHandle)->txFont, &tempString);
- theData = NewHandle(tempString[0]);
- HLock(theData);
- BlockMove((Ptr)&tempString[1], (Ptr)*theData, tempString[0]);
- HUnlock(theData);
- (*propertyTokenH)->theData = theData;
-
- break;
- case pPointSize:
- /* Object Class ID: cFixed16 */
- (*propertyTokenH)->theDataType = typeFixed;
- theData = NewHandleClear(sizeof(long));
- *((short *)*theData) = (*(*propertyTokenH)->token.textHandle)->txSize;
- (*propertyTokenH)->theData = theData;
-
- case pScriptTag:
- (*propertyTokenH)->theDataType = typeIntlWritingCode;
- theData = NewHandle(sizeof(WritingCode));
- theCode = (WritingCodePtr) *theData;
- HLock(theData);
- theCode->theScriptCode = FontScript();
- theCode->theLangCode = iuSystemCurLang;
- HUnlock(theData);
- (*propertyTokenH)->theData = theData;
-
- break;
- case pTextStyles:
- /* in my sample, no style */
- (*propertyTokenH)->theDataType = typeBoolean;
- theData = NewHandle(sizeof(short));
- **theData = false; /* we have no style */
- (*propertyTokenH)->theData = theData;
-
- break;
- /*****************************/
-
- } /* endswitch */
-
-
- return(myErr);
- }
-
- pascal OSErr PropertyFromShape(DescType desiredClass, const AEDesc *container, DescType containerClass, DescType form,
- const AEDesc *selectionData, AEDesc *value, long LongInt)
- {
- #pragma unused (desiredClass,containerClass,form,LongInt)
- OSErr myErr = noErr;
- PropertyTHdl propertyTokenH = (PropertyTHdl)NewHandleClear(sizeof(PropertyToken));
- /* pull a property from the window */
- CShapeObjHandle theShapeToken; /* the token for this shape */
- RGBColor white = {
- 0xFFFF, 0xFFFF, 0xFFFF
- };
- ShapesHandle theShape;
- short penSize = 1;
- long myCopy = 0;
- DescType propertyType = *(DescType *)(*(selectionData->dataHandle));
- Handle theData;
- windowCHandle owningControl;
- DescType shapeType;
- mVerboseOutput("\p\n Getting a property from a shape")
- theShapeToken = (CShapeObjHandle)container->dataHandle;
- owningControl = (windowCHandle)GetWRefCon((*theShapeToken)->theOwningWindow);
- shapeType = (*theShapeToken)->type;
- theShape = (*theShapeToken)->theShape;
- (*propertyTokenH)->owningTokenType = shapeType;
- (*propertyTokenH)->token.shapeHandle = (*theShapeToken)->theShape;
- (*propertyTokenH)->theProperty = propertyType;
- (*propertyTokenH)->inWindow = (*theShapeToken)->theOwningWindow;
- /* so after filling in a bunch, all we need now is the data type and the data itself */
- switch (propertyType) {
- case pBounds:
- case pDefinitionRect:
- /* This is the same as the bounds rect in my example */
-
- /* return a bounds rect, pretty easy */
- (*propertyTokenH)->theDataType = typeQDRectangle;
- theData = NewHandle(sizeof(Rect));
- HLock(theData);
- BlockMove((Ptr)&(*theShape)->theRect, (Ptr)*theData, sizeof(Rect));
- /* this of course stays in local coordinates for the owning port */
- (*propertyTokenH)->theData;
- break;
- case pClass:
- (*propertyTokenH)->theDataType = typeType;
- theData = NewHandle(sizeof(DescType));
- HLock(theData);
- /* I know, blockmoving 4 bytes is silly. */
- BlockMove((Ptr)&shapeType, (Ptr)*theData, sizeof(DescType));
- break;
- case pFillColor:
- (*propertyTokenH)->theDataType = typeRGBColor;
- /* always white in this example */
- theData = NewHandle(sizeof(RGBColor));
- HLock(theData);
- BlockMove((Ptr)&white, (Ptr)*theData, sizeof(RGBColor));
- HUnlock(theData);
- (*propertyTokenH)->theData = theData;
-
- break;
- case pFillPattern:
- case pPenPattern:
- break;
- case pPenColor:
- (*propertyTokenH)->theDataType = typeRGBColor;
- theData = NewHandle(sizeof(RGBColor));
- HLock(theData);
- BlockMove((Ptr)&(*theShape)->theColor, (Ptr)*theData, sizeof(RGBColor));
- HUnlock(theData);
- (*propertyTokenH)->theData = theData;
-
- break;
-
- case pPenWidth:
- (*propertyTokenH)->theDataType = typeShortInteger;
- /* always white in this example */
- theData = NewHandle(sizeof(short));
- HLock(theData);
- BlockMove((Ptr)&penSize, (Ptr)*theData, sizeof(short));
- break;
- case pTransferMode:
- (*propertyTokenH)->theDataType = typeEnumeration;
- /* always white in this example */
- theData = NewHandle(sizeof(long));
- HLock(theData);
- BlockMove((Ptr)&myCopy, (Ptr)*theData, sizeof(long));
- break;
- }
- HUnlock(theData);
- /* dangme I forgot to move what I just did into result..... */
- if (!myErr) {
- HLock((Handle)propertyTokenH);
- myErr = AECreateDesc(typeProperty, (Ptr)*propertyTokenH, sizeof(PropertyToken), value);
- /* dispose of the token handle, but NOT the data handle I added, since the AEM */
- /* had no idea that I put a handle inside the data, so it didn't copy that */
- /* Later, when the token itself is disposed that handle will be */
- /* freed up. */
- DisposeHandle((Handle)propertyTokenH);
- mAEErrorDisplay("\p creating property token", myErr);
-
- }
-
- return(myErr);
- }
-
-
- /* You may never need a dispose function. If all you use for tokens are */
- /* simple AEDescs, the OSL will do all the disposal for you. */
- /* In my case, my tokens contain handles, so I have to */
- /* do some disposal myself. */
- pascal OSErr MyDisposeTokenProc(AEDesc *unneededToken)
- {
- OSErr myErr = noErr;
- PropertyTHdl myProp;
- mVerboseOutput("\p\nDisposing a Token: ")
- AddToAEWindow((Ptr)&(unneededToken->descriptorType), kFour);
- /* most of the time I'll be doing a simple AEDisposeDesc. The only time I need */
- /* something more complex is when I'm disposing of a property descriptor, since */
- /* I have a handle inside that */
- switch (unneededToken->descriptorType) {
- /* these two are simple */
- case cWindow:
- case cText:
- myErr = AEDisposeDesc(unneededToken);
- break;
- /* these two have imbedded handles */
- case cWord:
- myErr = AEDisposeDesc(unneededToken);
- break;
- case typeProperty:
- myProp = (PropertyTHdl)unneededToken->dataHandle;
- DisposeHandle((*myProp)->theData);
- myErr = AEDisposeDesc(unneededToken);
-
- break;
-
- default:
- /* I default to just disposing of the token, ne ces pa */
- AEDisposeDesc(unneededToken);
- break;
- }
- return(myErr);
- }
-
- /* not yet implemented (and also not installed as a callback) */
- pascal OSErr MyCompareProc(DescType oper, const AEDesc *obj1, const AEDesc *obj2, Boolean *result)
- {
- #pragma unused (oper,obj1,obj2,result)
- OSErr myErr = noErr;
- mVerboseOutput("\p\nComparing Objects")
- return(myErr);
- }
-
- pascal OSErr MyCountProc(DescType desiredType, DescType containerClass, const AEDesc *container, long *result)
- {
- OSErr myErr = noErr;
- long counter = 0;
- WindowPtr windows;
- windowCHandle tempWC;
- switch (desiredType) {
- case cWindow:
- /* should be conting windows from nul */
- mVerboseOutput("\p\nCounting Windows")
- windows = (WindowPtr)LMGetWindowList();
- while (windows) {
- counter++;
- windows = (WindowPtr)((WindowPeek)windows)->nextWindow;
- }
- *result = counter;
- break;
- case kAEMyShape:
- mVerboseOutput("\p\nCounting Shapes")
- /* getting this from a specific container, i.e. a winder. */
- switch (containerClass) {
- case cWindow:
- case cDrawingArea:
- /* we're OK so far */
- /* get my window pointer from the container passed */
- CountShapes(container,&counter,nil,nil,&desiredType);
- *result = counter;
- break;
- case typeNull:
- /* this would mean all the possible shapes */
- break;
- }
- break;
- case cText:
- mVerboseOutput("\p\nCounting Texts")
- switch (containerClass) {
- /* I can count texts in a window and in Null (the app) */
- case typeNull:
- /* walk all my document windows and see how many texts exisit */
- windows = FrontWindow();
- /* there may not be any, o'course */
- while (windows) {
- tempWC = (windowCHandle)GetWRefCon(windows);
- if ((*tempWC)->boxHandle)
- counter++;
- windows = (WindowPtr)((WindowPeek)windows)->nextWindow;
- }
- *result = counter;
- break;
- case cWindow:
- /* so we know the container desc is my window token */
- windows = (WindowPtr)*(container->dataHandle);
- tempWC = (windowCHandle)GetWRefCon(windows);
- /* there is either one or none */
- *result = (((*tempWC)->boxHandle) ? 1 : 0);
- break;
- default:
- mVerboseOutput("\p\nAsked for text count from something we don't understand ")
- myErr = errAECantHandleClass;
- /* add new Winter '92 registry error code <ckh 1.0.2>*/
- AddToReply("\p Cant count this class",errAECantHandleClass);
-
- counter = 0;
- break;
- }
- *result = counter;
- break;
- case cWord:
- /* Since I have to count words in another place (when I get the word) */
- /* I will call my subroutine, saying I don't want to stop */
- mVerboseOutput("\p\nCounting Words ")
- CountWords(container, &counter, nil, nil);
- *result = counter;
- break;
- case cGraphicLine:
- case cRectangle:
- case cOval:
- case cGraphicShape:
- /* all these are basically the same */
- CountShapes(container, &counter, nil, nil, &desiredType);
- *result = counter;
- break;
- default:
- myErr = errAENoSuchObject; /* I don't know what's being asked for */
- break;
-
- }
- return(myErr);
- }
-
- void CountWords(const AEDesc *container, long *theCount, long stopAt, long *position)
- {
- CTextObjHandle ourTextObject;
- Handle theText;
- SignedByte textState;
- char *textPtr;
- register char letter;
- long wordCount = 1; /* I'm getting passed a 1 based count to find */
- Boolean inSpaces = false;
- register long positionNow = 0;
- long lastLetter = 0;
- /* So we have a text object here, which contains a TEHandle */
- /* We step through the handle counting words */
- /* get the text from my cText token */
-
- AddAENum(stopAt);
- ourTextObject = (CTextObjHandle)(container->dataHandle);
- *position = -1;
- theText = (Handle)TEGetText((*ourTextObject)->theText);
- textState = HGetState(theText);
- HLock(theText); /* AddAENum makes some TextEdit calls, so I need to lock this */
- /* how many characters are in it? */
- lastLetter = GetHandleSize(theText);
- if (lastLetter) {
- /* now this is a slow and agonizing word count routine, it's not intended to be any more than that */
- textPtr = (char *)*theText;
- for (positionNow = 0; positionNow < lastLetter; positionNow++) {
- letter = *(textPtr + positionNow);
- if (letter == kSpace) {
- if (!inSpaces)
- wordCount++;
- inSpaces = kMyTrue;
- if (stopAt && stopAt == wordCount) {
- if (position)
- *position = positionNow;
- break;
- }
- } else {
- inSpaces = false;
- }
- }
- /* Did we have fun counting words? Yes? */
- /* OK, we have a word count */
- /* if position is still negative, we didn't get to this word. Maybe there weren't enough */
- if (*position >= 0)
- *theCount = wordCount;
- else
- *theCount = -1;
- AddAENum(wordCount);
- } else {
- /* no words (or letters) in this thing */
- *theCount = -1;
- }
- HSetState(theText, textState);
- }
-
- void CountShapes(const AEDesc *container, long *theCount, long stopAt, long *position, DescType *whichType)
- {
- #pragma unused (stopAt,position)
- WindowPtr owner;
- windowCHandle tempWCH;
- ShapesHandle theShapes;
- mVerboseOutput("\p\nCounting Shapes ")
- if (container->descriptorType == cWindow || container->descriptorType == cDrawingArea) {
- owner = *((WindowPtr *)(*(container->dataHandle)));
- tempWCH = (windowCHandle)GetWRefCon(owner);
- if(*whichType == cGraphicShape){
- *theCount = (*tempWCH)->numShapes;
- } else {
- /* find specific things */
- *theCount = 0;
- theShapes = (*tempWCH)->theShapes;
- while(theShapes){
- if((*theShapes)->aeType == *whichType)*theCount +=1;
- theShapes = (*theShapes)->nextShape;
- }
- }
-
- } else {
- /* no luck joe, can't count items from this container */
- *theCount = -1;
- }
- }
-
- /* not yet implemented (and also not installed as a callback) */
- pascal OSErr MyGetMarkTokenProc(const AEDesc *dContainerToken, DescType containerClass, AEDesc *result)
- {
- #pragma unused (dContainerToken,containerClass,result)
- OSErr myErr = noErr;
- mVerboseOutput("\p\nGetting a Mark token")
- return(myErr);
- }
-
- /* not yet implemented (and also not installed as a callback) */
- pascal OSErr MyMarkProc(const AEDesc *dToken, const AEDesc *markToken, long index)
- {
- OSErr myErr = noErr;
- #pragma unused (dToken,markToken,index)
- mVerboseOutput("\p\nMarking something")
- return(myErr);
- }
-
- /* not yet implemented (and also not installed as a callback) */
- pascal OSErr MyAdjustMarksProc(long newStart, long newStop, const AEDesc *markToken)
- {
- #pragma unused (newStart,newStop,markToken)
- OSErr myErr = noErr;
- mVerboseOutput("\p\nAdjusting Marks")
- return(myErr);
- }
-
- /* This builds our GetData event, based on the things you've set up in the object */
- /* definition dialogs. */
- OSErr BuildGetDataEvent(AppleEvent *thisEvent, short which)
- {
- OSErr myErr = noErr;
- AEDesc object;
- myErr = BuildFullObject(&object, which);
- myErr = AEPutParamDesc(thisEvent, keyDirectObject, &object);
- mAEErrorDisplay("\p putting object", myErr)
- if (!myErr)
- AEDisposeDesc(&object);
- /* one last thing to deal with. We _can_, if we want, add a keyAERequestedType parameter. */
- /* this is optional, and specifies the format of the data we'd like to work with. */
- /* NOTE: The receiver of this event may ignore this completely. There may be */
- /* two reasons for the ignoring.... */
- /* 1) It's an optional param. That means the receiver may not even look for it, or */
- /* know it's there. */
- /* 2) They may not be able to do it. They may not be able to coerce their data to the */
- /* type you'd like to get back. If so, they'll still send data back, it'll just */
- /* be in the standard format (as described in the registry) for this event and object. */
- /* You will have to do the coercion yourself. */
- /* By The Way: If you add system level coercion routines for the types you like to see */
- /* other apps on the same machine will be able to coerce to your types without having any */
- /* understanding of them. */
- /* By The Way II: If you do not get back the type you want, you should also */
- /* try and coerce it yourself. Perhaps you have the correct coercion */
- /* routine on your machine, one that was not available to the other app. */
- return(myErr);
- }
-
- /* This builds our SetData event, based on the things you've set up in the object */
- /* definition dialogs. */
- /* It's a little more complicated, since I have to throw in dialogs to get the */
- /* new value you want */
-
- OSErr BuildSetDataEvent(AppleEvent *thisEvent, short which)
- {
- OSErr myErr = noErr;
- DialogPtr tdial;
- short strung;
- RGBColor oldColor = {0,0,0};
- RGBColor newColor;
- Str63 paramString;
- short hitItem = 0;
- DescType theDataDesc;
- short doVis;
- short *tempShortPtr;
- Handle theDataHandle = NewHandle(0);
- AEDesc object;
- AEDesc dataToSet;
- /* build the window based on previous things (from dialog) */
- myErr = BuildFullObject(&object, which);
- mAEErrorDisplay("\p putting object", myErr)
- if (!myErr) {
- /* We've got the object built. Since this is a SetData event, now we have to add the */
- /* actual data to set to the thing. Yes kids, its DialogBox time.... */
- /* There's nothing interesting here except dialog box handling, if you want to get */
- /* on to Objects and Æs again, skip ahead to ••here•• */
- tdial = CommonDStart(kSetDDialog, 0, 0);
- /* show the correct items */
- switch (which) {
- case kWindowBoundsItem:
- ShowDialogItem(tdial, kRectTextItem);
- ShowDialogItem(tdial, kRectEdit1);
- ShowDialogItem(tdial, kRectEdit2);
- ShowDialogItem(tdial, kRectEdit3);
- ShowDialogItem(tdial, kRectEdit4);
- break;
- case kWindowTitleItem:
- ShowDialogItem(tdial, kNewTitleWordsItem);
- ShowDialogItem(tdial, kNewTitleEditLineItem);
- break;
- case kWindowVisiblityItem:
- ShowDialogItem(tdial, kMakeVisItem);
- ShowDialogItem(tdial, kMakeInvisItem);
-
- break;
- case kAllText:
- ShowDialogItem(tdial, kNewTextItem);
- ShowDialogItem(tdial, kNewText);
-
- break;
- case kWordText:
- ShowDialogItem(tdial, kNewWordItem);
- ShowDialogItem(tdial, kNewText);
-
- break;
- case kShapeItem:
- ShowDialogItem(tdial, kNewSBoundsRadio);
- ShowDialogItem(tdial, kNewSColorRadio);
- ShowDialogItem(tdial, kNewSColorButton);
- ShowDialogItem(tdial, kRectEdit1);
- ShowDialogItem(tdial, kRectEdit2);
- ShowDialogItem(tdial, kRectEdit3);
- ShowDialogItem(tdial, kRectEdit4);
- HiliteControl(SnatchHandle(tdial, kNewSColorButton),255);
- SetControlValue(SnatchHandle(tdial, kNewSBoundsRadio), true);
- break;
- }
- if(which != kShapeItem)
- strung = which - 1 + kSettingVis;
- else
- strung = kSettingShape;
- GetIndString(paramString, kGeneralStrings, strung);
- /* I'm going to add a little more text here */
- if(which == kShapeItem)
- {DescType shapeTypes[] = {
- cGraphicLine, cRectangle, cOval
- };
- Str32 theNum;
- HLock((Handle)gShapeObjSpecHandle);
- theNum[0] = 6;
- theNum[1] = ' ';
- BlockMove((Ptr)&(*gShapeObjSpecHandle)->form,(Ptr)&theNum[2],kFour);
- theNum[6] = ' ';
- AppendString(¶mString,&theNum);
- NumToString((*gShapeObjSpecHandle)->u.index,&theNum);
- AppendString(¶mString,&theNum);
- HUnlock((Handle)gShapeObjSpecHandle);
-
- }
- ParamText(paramString, "", "", "");
- ShowWindow(tdial);
- DrawDialog(tdial);
- if (which == kWindowVisiblityItem)
- SetControlValue(SnatchHandle(tdial, kMakeVisItem), true);
- doVis = true;
-
- {
- ModalFilterUPP upp = NewModalFilterProc(standardDialogFilter);
- while (hitItem != ok && hitItem != cancel) {
- ModalDialog(upp, &hitItem);
- /* the only one that has anything we need to set is the visibility one */
- if (which == kWindowVisiblityItem) {
- if (hitItem == kMakeVisItem || hitItem == kMakeInvisItem) {
- SetControlValue(SnatchHandle(tdial, kMakeVisItem), false);
- SetControlValue(SnatchHandle(tdial, kMakeInvisItem), false);
- SetControlValue(SnatchHandle(tdial, hitItem), true);
- }
- }
- if (which == kShapeItem) {
- switch (hitItem){
- Point where;
- case kNewSBoundsRadio:
- case kNewSColorRadio:
- SetControlValue(SnatchHandle(tdial, kNewSBoundsRadio), false);
- SetControlValue(SnatchHandle(tdial, kNewSColorRadio), false);
- SetControlValue(SnatchHandle(tdial, hitItem), true);
- if(GetControlValue(SnatchHandle(tdial, kNewSColorRadio)))
- HiliteControl(SnatchHandle(tdial, kNewSColorButton),0);
- else
- HiliteControl(SnatchHandle(tdial, kNewSColorButton),255);
- break;
- case kNewSColorButton:
- GetIndString(paramString, kGeneralStrings, kNewSCol);
- where.v = -1;
- where.h = -1;
- GetColor(where,paramString,&oldColor,&newColor);
- break;
- }
- }
- }
- DisposeRoutineDescriptor(upp);
- }
-
- if (hitItem == 1) {
- /* and one more switch, pull parameters and create the actual data descriptor that */
- /* we will pass along in the SetData event. */
- /* ••here•• */
- /* pull the various parameters for the data to set, create a Desc to hold them, */
- /* and add that desc to our event */
- switch (which) {
- Str255 tempString;
- long theNum;
- register qq;
- case kWindowBoundsItem:
- theDataDesc = typeQDRectangle;
- /* ugg. Go through all the edit lines and make a rect */
- SetHandleSize(theDataHandle, sizeof(Rect));
- tempShortPtr = (short *)*theDataHandle;
- HLock(theDataHandle);
- for (qq = kRectEdit1; qq < kRectEdit4 + 1; qq++) {
- GetDialogItemText((Handle)SnatchHandle(tdial, qq), tempString);
- StringToNum(tempString, &theNum);
- *tempShortPtr = theNum;
- tempShortPtr = tempShortPtr + 1; /* I have had problems with MPW C dealing with a += on a pointer, so I don't do it */
- }
- break;
- case kWindowTitleItem:
- theDataDesc = typeChar;
- GetDialogItemText((Handle)SnatchHandle(tdial, kNewTitleEditLineItem), tempString);
- SetHandleSize(theDataHandle, tempString[0]);
- /* move the text into the handle */
- HLock(theDataHandle);
- BlockMove((Ptr)&tempString[1], (Ptr)*theDataHandle, tempString[0]);
- /* leave the data handle locked for later */
- break;
- case kWindowVisiblityItem:
- theDataDesc = typeBoolean;
- doVis = GetControlValue(SnatchHandle(tdial, kMakeVisItem));
- SetHandleSize(theDataHandle, sizeof(short)); /* a boolean is short length */
- HLock(theDataHandle); /* for later */
- tempShortPtr = (short *)*theDataHandle;
- *tempShortPtr = (doVis ? -1 : false);
- break;
- case kAllText:
- case kWordText:
- /* these are both the same */
- theDataDesc = typeChar;
- GetDialogItemText((Handle)SnatchHandle(tdial, kNewText), tempString);
- SetHandleSize(theDataHandle, tempString[0]);
- /* move the text into the handle */
- HLock(theDataHandle);
- BlockMove((Ptr)&tempString[1], (Ptr)*theDataHandle, tempString[0]);
-
- break;
- case kShapeItem:
- /* make the parameters for the shape change */
- if(GetControlValue(SnatchHandle(tdial, kNewSColorRadio))){
- /* setting color, the color is in newColor */
- theDataDesc = typeRGBColor;
- SetHandleSize(theDataHandle, sizeof(RGBColor));
- HLock(theDataHandle);
- BlockMove((Ptr)&newColor,*theDataHandle,sizeof(RGBColor));
-
- } else {
- /* setting rect, same stuff as window */
- theDataDesc = typeQDRectangle;
- SetHandleSize(theDataHandle, sizeof(Rect));
- tempShortPtr = (short *)*theDataHandle;
- HLock(theDataHandle);
- for (qq = kRectEdit1; qq < kRectEdit4 + 1; qq++) {
- GetDialogItemText((Handle)SnatchHandle(tdial, qq), tempString);
- StringToNum(tempString, &theNum);
- *tempShortPtr = theNum;
- tempShortPtr = tempShortPtr + 1; /* I have had problems with MPW C dealing with a += on a pointer, so I don't do it */
- }
-
-
-
- }
- AddShapeProperty(&object,GetControlValue(SnatchHandle(tdial, kNewSColorRadio)));
- break;
- }
- } else {
- myErr = userCanceledErr;
- }
- DisposeDialog(tdial);
- /* dialog is gone, the data we want is in theDataHandle, the descriptor type is in theDataDesc, */
- /* it's time to put the data on the event. */
- /* create a desc to hold it */
- if (hitItem == 1) {
- /* put the object into the event now */
- myErr = AEPutParamDesc(thisEvent, keyDirectObject, &object);
- AEDisposeDesc(&object);
-
-
-
- myErr = AECreateDesc(theDataDesc, (Ptr)*theDataHandle, GetHandleSize(theDataHandle), &dataToSet);
- DisposeHandle(theDataHandle); /* don't need this anymore */
- if (!myErr) {
- /* the desc created fine. Add this to the event */
- myErr = AEPutParamDesc(thisEvent, keyAEData, &dataToSet);
- myErr = AEDisposeDesc(&dataToSet);
- /* and the event is all ready to be sent by the caller, so we return */
- }
- } else {
- myErr = userCanceledErr;
- }
- }
- return(myErr);
- }
-
- /* BuildFullObject builds an object specifier based on the parameters set in */
- /* the object dialogs in this sample. */
- OSErr BuildFullObject(AEDesc *object, short which)
- {
- OSErr myErr = noErr;
- AEDesc tempDesc;
- AEDesc otherTemp;
- long number1 = 1;
- DescType Props[3] = {
- pBounds, pName, pVisible
- };
-
- BuildWindowObject(object);
- switch (which) {
- /* we already have a window object, so for the first three, create a property desc and type */
- /* since we're only working with the properties of windows */
- case kWindowBoundsItem:
- case kWindowTitleItem:
- case kWindowVisiblityItem:
- AEDuplicateDesc(object, &otherTemp);
- myErr = AECreateDesc(typeType, (Ptr)&Props[which - 1], kFour, &tempDesc);
- myErr = CreateObjSpecifier(typeProperty, &otherTemp, formPropertyID, &tempDesc, true, object);
-
- break;
-
- case kAllText:
- /* we're asking for all the text in the window */
- AEDuplicateDesc(object, &otherTemp);
- HLock((Handle)gTextObjSpecHandle);
- if ((*gTextObjSpecHandle)->u.index == 0)
- (*gTextObjSpecHandle)->u.index = 1;
- myErr = AECreateDesc(typeLongInteger, (Ptr)&(*gTextObjSpecHandle)->u.index, sizeof(long), &tempDesc);
-
- myErr = CreateObjSpecifier(cText, &otherTemp, formAbsolutePosition, &tempDesc, true, object);
-
- HUnlock((Handle)gTextObjSpecHandle);
- break;
- case kWordText:
- /* one word from the window and text object */
- AEDuplicateDesc(object, &otherTemp);
- HLock((Handle)gTextObjSpecHandle);
- if ((*gTextObjSpecHandle)->u.index == 0)
- (*gTextObjSpecHandle)->u.index = 1;
- myErr = AECreateDesc(typeLongInteger, (Ptr)&(*gTextObjSpecHandle)->u.index, sizeof(long), &tempDesc);
-
- myErr = CreateObjSpecifier(cText, &otherTemp, formAbsolutePosition, &tempDesc, true, object);
- AEDuplicateDesc(object, &otherTemp);
- if ((*gTextObjSpecHandle)->wordNumber == 0)
- (*gTextObjSpecHandle)->wordNumber = 0;
- myErr = AECreateDesc(typeLongInteger, (Ptr)&(*gTextObjSpecHandle)->wordNumber, sizeof(long), &tempDesc);
- myErr = CreateObjSpecifier(cWord, &otherTemp, formAbsolutePosition, &tempDesc, true, object);
-
- HUnlock((Handle)gTextObjSpecHandle);
- break;
- /* for these, we have to add the additional cDrawingArea container */
- case kShapeItem:
- AEDuplicateDesc(object, &otherTemp);
- /* this always defaults to 1, we have only one drawing area per window */
- AECreateDesc(typeLongInteger, (Ptr)&number1, sizeof(long), &tempDesc);
- myErr = CreateObjSpecifier(cDrawingArea, &otherTemp, formAbsolutePosition, &tempDesc, true, object);
- /* now which the thing */
-
- myErr = CreateShapeObject(object);
- break;
- }
- mAEErrorDisplay("\p creating object", myErr)
-
- return(myErr);
-
- }
- /* BuildWindowObject builds a window object from null, based on the parameters you have */
- /* specified in the dialog boxes */
- OSErr BuildWindowObject(AEDesc *returnedObject)
- {
- long theLong = 1;
- OSErr myErr = noErr;
- AEDesc containerDesc;
- AEDesc theIdentifier;
- /* establish some defaults so the object will be right even if the Window Object dialog hasn't been used */
- DescType theForm = formAbsolutePosition;
- long number1 = 1;
- HLock((Handle)gWindObjSpecHandle);
- switch ((*gWindObjSpecHandle)->form) {
- case formAbsolutePosition:
- theForm = formAbsolutePosition;
- /* make an abs for spec */
- /* What?? What that comment really meant, was create an object specifier for a window */
- /* based on the data we have stored in our window descriptor object, that's */
- /* set with the dialog, based on absolute position or name */
- if ((*gWindObjSpecHandle)->u.index == 0)
- (*gWindObjSpecHandle)->u.index = 1;
- myErr = AECreateDesc(typeLongInteger, (Ptr)&(*gWindObjSpecHandle)->u.index, sizeof(long), &theIdentifier);
-
- break;
- case formName:
- /* make an object specifier based on window name */
-
- theForm = formName;
- myErr = AECreateDesc(typeChar, (Ptr)&(*gWindObjSpecHandle)->u.name[1], (*gWindObjSpecHandle)->u.name[0],
- &theIdentifier);
- break;
- default:
- /* defaults to a byindex, window one spec if nothing else has been set up */
- myErr = AECreateDesc(typeLongInteger, (Ptr)&number1, sizeof(long), &theIdentifier);
- break;
- }
- mAEErrorDisplay("\p creating formProperty for this thing", myErr)
- /* Every event will act on a window */
-
- /* we're always adding windows from nul, so duplicate nul */
- AEDuplicateDesc(&gNullDesc, &containerDesc);
-
- /* build a window object contained in nul */
- myErr = CreateObjSpecifier(cWindow, &containerDesc, theForm, &theIdentifier, true, returnedObject);
- mAEErrorDisplay("\p creating window object", myErr)
- HUnlock((Handle)gWindObjSpecHandle);
- return(myErr);
- }
-
- /* CreateShapeObject attached the shape object to the basic specifier */
- /* already created (nul>cWindow>cDrawingArea) */
- /* Since all my shapes are basically the same, we have one routine to do this for us */
-
- OSErr CreateShapeObject(AEDesc *theContainer)
- {
- AEDesc tempDesc;
- AEDesc indexDesc;
- DescType theType;
- OSErr myErr = noErr;
- HLock((Handle)gShapeObjSpecHandle);
- theType = (*gShapeObjSpecHandle)->form;
- /* duplicate what we have so far */
- AEDuplicateDesc(theContainer, &tempDesc);
- /* In this example, we're only implementing a ByIndex form for graphics, so... */
- if ((*gShapeObjSpecHandle)->u.index == 0)
- (*gShapeObjSpecHandle)->u.index = 1;
- myErr = AECreateDesc(typeLongInteger, (Ptr)&(*gShapeObjSpecHandle)->u.index, sizeof(long), &indexDesc);
- myErr = CreateObjSpecifier(theType, &tempDesc, formAbsolutePosition, &indexDesc, true, theContainer);
- HUnlock((Handle)gShapeObjSpecHandle);
- return(myErr);
- }
-
- /* AddShapeProperty tacks a property specifier onto an already created shape specifier */
- OSErr AddShapeProperty(AEDesc *theObject,Boolean which)
- {
- AEDesc tempDesc,otherTemp;
- DescType theProp;
- OSErr myErr = noErr;
- if(which)
- theProp = pPenColor;
- else
- theProp = pBounds;
- myErr = AEDuplicateDesc(theObject, &otherTemp);
- myErr |= AECreateDesc(typeType,(Ptr) &theProp, kFour, &tempDesc);
- myErr |= CreateObjSpecifier(typeProperty, &otherTemp, formPropertyID, &tempDesc, true, theObject);
-
- return(myErr);
- }
-
- #undef __AEOBJ__
-